Skip to content

feat(ci): surface merge-queue needs-validation ejection as a PR comment - #5519

Merged
lefarcen merged 1 commit into
mainfrom
feat/merge-queue-needs-validation-comment
Jul 13, 2026
Merged

feat(ci): surface merge-queue needs-validation ejection as a PR comment#5519
lefarcen merged 1 commit into
mainfrom
feat/merge-queue-needs-validation-comment

Conversation

@lefarcen

Copy link
Copy Markdown
Contributor

Why

While driving #5329 to merge we hit the needs-validation gate's blind spot first-hand: the PR was approved, every check on the head was green, enqueuePullRequest succeeded — and then the PR silently fell out of the merge queue. Nothing on the PR said why. mergeQueueEntry just went null, the head stayed CLEAN, and the actual reason (PR #5329 still has 'needs-validation' — blocking merge) lived in a merge_group workflow run that no surface links back to the PR. The gate's own design comment acknowledges this ("this failure does NOT appear in the PR head's status rollup") — that is correct and intentional for keeping PR checks green, but it currently means every ejection costs someone a manual dig through gh run list --event merge_group.

This closes that gap: an ejection now leaves a visible, actionable trace on the PR itself.

What users will see

When a queued PR is ejected because it still carries the needs-validation label, the PR gets a bot comment (upserted, so repeated ejections update one comment instead of stacking):

Ejected from the merge queue: this PR still carries the needs-validation label.

The merge queue gate (run …) blocked the queued group because of the label. That failure runs on the queue's transient ref, so it never appears in this PR's own checks — they stay green, and this notice is the only visible trace on the PR.

To land this PR: complete the QA pass the label is tracking, remove the needs-validation label, then add the PR back to the merge queue.

No change for PRs without the label, and no change to the gate's blocking semantics.

How

Follows the ci.yml producer + comment.atom.yml consumer topology from .github/AGENTS.md:

  • Producer (ci.yml, validate job): the merge_group gate emits a handoff/comment artifact via .github/scripts/handoff.py for the labeled PR right before exit 1, and an if: failure() && … step uploads it (the gate fails exactly when it produces). A sparse checkout of .github (merge_group runs only) makes the helper available; production is best-effort and can never soften the block itself. Fail-fast keeps one notice per run — every labeled entry also fails its own queue run, so each still gets its own notice.
  • Consumer (comment.atom.yml): now accepts merge_group workflow_run events. A merge_group run's head_sha is the queue's synthetic merge commit, never the PR head, so artifacts from those runs are bound to their producing run by run_id (already part of the handoff contract — no handoff.py changes needed). The base-freshness skip is waived for merge_group (PRs ahead in the queue merge into the base while the run completes, so the base is expected to move); the live-PR head/state/draft checks still guard staleness. autofix.atom.yml and report.atom.yml deliberately stay pull_request-only.
  • Topology tests (e2e/tests/packaged-smoke-workflow.test.ts): the trusted-consumer test now pins comment.atom to pull_request || merge_group and asserts autofix/report do not consume merge_group; a new case covers the producer/consumer pair for the ejection notice.

Surface area

  • UI
  • Keyboard shortcut
  • CLI / env var
  • API / contract
  • Extension point
  • i18n keys
  • New top-level dependency
  • Default behavior change
  • None — GitHub automation only (new bot comment on merge-queue ejection)

Test plan

  • python3 .github/scripts/handoff.py self-check
  • actionlint on both modified workflows — clean
  • bash -n on both extracted run: blocks
  • Local dry-run of the producer function against real PR data (feat(chat): map long-tail failure_detail values to specific run-error cards #5329): artifact name, handoff.py validate comment, and the consumer-side list output (including run_id) all round-trip; body renders with the correct run link
  • pnpm --filter @open-design/e2e test tests/packaged-smoke-workflow.test.ts — 46/46 (includes the new topology case)
  • pnpm guard (78/0) and pnpm typecheck

Real-world validation happens on the first ejection after merge; the motivating repro is #5329's ejection run https://github.com/nexu-io/open-design/actions/runs/29222046956.

A PR ejected from the merge queue by the needs-validation gate leaves no
trace on the PR itself: the gate fails on the queue's transient ref, the
PR's own checks stay green, and mergeQueueEntry silently goes null. The
only way to learn why the PR fell out of the queue is to dig through
merge_group workflow runs, which nobody watches (observed on #5329).

Producer: the merge_group gate in ci.yml now emits a handoff/comment
artifact targeting the labeled PR right before it blocks, and uploads it
on the failure path. Consumer: comment.atom.yml accepts merge_group
workflow_run events; since a merge_group run's head_sha is the queue's
synthetic merge commit, artifacts from those runs are bound to their
producing run by run_id, and the base-freshness skip is waived (PRs
ahead in the queue move the base while the run completes). The live-PR
head check still guards staleness.

Topology coverage pins the new boundary: comment.atom consumes
pull_request + merge_group; autofix/report stay pull_request-only.
@lefarcen
lefarcen requested a review from a team as a code owner July 13, 2026 04:49
@lefarcen lefarcen added size/M PR changes 100-300 lines risk/high High risk: apps/desktop, daemon, auth, migration, workflows, package deps type/chore CI / build / config / tooling labels Jul 13, 2026
@lefarcen
lefarcen requested a review from PerishCode July 13, 2026 04:52
@lefarcen

Copy link
Copy Markdown
Contributor Author

Quick template nit: the motivation and rollout details are clear, but the PR body is still missing a ## Validation section for the current template.

The existing ## Test plan already covers most of it, so a short validation summary that says what actually ran should be enough.

@lefarcen lefarcen added the skip-validation Maintainer override: bot will not auto-add needs-validation on this PR. label Jul 13, 2026

@PerishCode PerishCode left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lefarcen I reviewed the workflow and topology-test changes for the merge-queue needs-validation ejection path. The producer keeps the existing merge_group gate semantics intact while emitting a validated handoff/comment artifact on the blocking path, and the comment atom’s merge_group handling still keeps the live PR head/state/draft checks in place while avoiding the synthetic queue head/base mismatch. The e2e topology coverage also pins the intended consumer boundary so autofix/report stay pull_request-only.

No actionable findings from this pass. Nice work making the queue ejection visible without changing the gate’s required-check behavior.

🔁 Powered by Looper · runner=reviewer · agent=codex · An autonomous AI dev team for your GitHub repos.

@lefarcen
lefarcen added this pull request to the merge queue Jul 13, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Visual regression review

Head: b6de866 · Base: 88b411e

1 changed · 52 unchanged · 0 new without baseline · 0 failed

Changed cases

Case Main PR Diff
visual-integrations-use-everywhere
1,149 px (0.09%)
main pr diff
Unchanged cases
Case Main PR Diff
visual-avatar-local-agent-list
0 px (0.00%)
main pr diff
visual-avatar-local-agent-list-panel
0 px (0.00%)
main pr diff
visual-avatar-menu
0 px (0.00%)
main pr diff
visual-avatar-menu-panel
0 px (0.00%)
main pr diff
visual-avatar-open-design-account
0 px (0.00%)
main pr diff
visual-critical-settings
0 px (0.00%)
main pr diff
visual-critical-workspace
0 px (0.00%)
main pr diff
visual-critical-workspace-preview
0 px (0.00%)
main pr diff
visual-design-system-detail
0 px (0.00%)
main pr diff
visual-design-systems
0 px (0.00%)
main pr diff
visual-home
0 px (0.00%)
main pr diff
visual-home-catalog
0 px (0.00%)
main pr diff
visual-home-context-picker
0 px (0.00%)
main pr diff
visual-home-context-picker-popover
0 px (0.00%)
main pr diff
visual-home-plugin-filter
0 px (0.00%)
main pr diff
visual-home-plugin-use-staged
0 px (0.00%)
main pr diff
visual-home-plugin-use-with-query
0 px (0.00%)
main pr diff
visual-home-staged-attachment
0 px (0.00%)
main pr diff
visual-integrations
0 px (0.00%)
main pr diff
visual-integrations-mcp
0 px (0.00%)
main pr diff

Visual diff is advisory only and does not block merging.

Merged via the queue into main with commit fc5b276 Jul 13, 2026
30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk/high High risk: apps/desktop, daemon, auth, migration, workflows, package deps size/M PR changes 100-300 lines skip-validation Maintainer override: bot will not auto-add needs-validation on this PR. type/chore CI / build / config / tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants